package com.nsl.my_youlai.bbu_return.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.nsl.my_youlai.bbu_return.convert.enums.*;


import com.nsl.my_youlai.bbu_return.exception.EnumTransformException;
import com.nsl.my_youlai.bbu_return.model.bo.BBUFrame;
import com.nsl.my_youlai.bbu_return.model.bo.BBUSlot;
import com.nsl.my_youlai.bbu_return.model.bo.BbuBoard;
import com.nsl.my_youlai.bbu_return.model.bo.check.CheckSchemeExcelRecord;
import com.nsl.my_youlai.bbu_return.model.vo.SchemeExcelRecord;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

//todo: 同一行，出现多个错误时，找到第一个错误就返回
//todo: 无槽道检查
@Slf4j
@Service
public class LoadNodeBInfoServiceImpl {



    /**
     * read scheme record 2 list
     * @param excelPath
     * @return
     */
    public void readBoardInfoSheet(String excelPath,List<SchemeExcelRecord> schemeExcelRecordList,List<CheckSchemeExcelRecord> checkSchemeExcelRecordList){
//        String fileName= NslUtilFilePath.getFilePathBasedOnClassPath("bbu\\附件1：BBU回局工程设计详表-南阳-V4_h.xlsx");
//        File file=new File(fileName);
//        System.out.println(file.exists());
        //List<SchemeExcelRecord> schemeExcelRecordList=new ArrayList<>();

        //List<CheckSchemeExcelRecord> checkSchemeExcelRecordList=new ArrayList<>();
        //BoardTypeEnumConvert2 boardTypeEnumConvert2=new BoardTypeEnumConvert2(BoardTypeEnum.class);
        EasyExcel.read(excelPath, SchemeExcelRecord.class, new ReadListener<SchemeExcelRecord>() {
            /**
             * 单次缓存的数据量
             */
            public static final int BATCH_COUNT = 100;
            /**
             *临时存储
             */
            private List<SchemeExcelRecord> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

            @Override
            public void invoke(SchemeExcelRecord data, AnalysisContext context) {
                data.setRowIndex(context.readRowHolder().getRowIndex());
                //log.info("data = {} ",data);
                cachedDataList.add(data);
                schemeExcelRecordList.add(data);
                if (cachedDataList.size() >= BATCH_COUNT) {
                    saveData();
                    // 存储完成清理 list
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                saveData();
            }

            /**
             * 加上存储数据库
             */
            private void saveData() {
               //log.info("{}条数据，开始存储数据库！", cachedDataList.size());
                //log.info("存储数据库成功！");
            }

            @Override
            public void onException(Exception exception, AnalysisContext context) {
                exception.printStackTrace();

                // 如果是某一个单元格的转换异常 能获取到具体行号
                // 如果要获取头的信息 配合invokeHeadMap使用
                //log.error(exception.getClass().getName());
                //log.error(exception.getCause().getMessage());
                //log.error(exception.getCause().getClass().getName());


                if (exception instanceof ExcelDataConvertException) {
                    ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
                    Throwable selfException=excelDataConvertException.getCause();
                    log.info("excelDataConvertException.getCellData().getStringValue() = {}",excelDataConvertException.getCellData().getStringValue());
                    if(selfException instanceof EnumTransformException){
                        EnumTransformException enumTransformException = (EnumTransformException)selfException;
                        log.error(enumTransformException.getMessage());
                        CheckSchemeExcelRecord checkSchemeExcelRecord=new CheckSchemeExcelRecord();
                        checkSchemeExcelRecord.setType("错误");
                        checkSchemeExcelRecord.setTitle(enumTransformException.getEnumCnName()+"错误");
                        checkSchemeExcelRecord.setRowIndex(excelDataConvertException.getRowIndex());
                        checkSchemeExcelRecord.setColumnIndex(excelDataConvertException.getColumnIndex());
                        checkSchemeExcelRecord.setExcelInputString(excelDataConvertException.getCellData().getStringValue());

                        checkSchemeExcelRecordList.add(checkSchemeExcelRecord);
                    }
                    log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                            excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
                    //throw new RuntimeException("第"+excelDataConvertException.getRowIndex()+"行 , 第" + (excelDataConvertException.getColumnIndex() + 1) + "列读取错误");
                }
//                if(exception.getCause() instanceof EnumTransformException){
//
//                }

                //抛出非空校验异常
                //throw new RuntimeException(exception.getMessage());
            }


        }).
                registerConverter(new GenerationTypeEnumConvert())
                .registerConverter(new BoardTypeEnumConvert())
                .registerConverter(new BbuModelEnumConvert())
                .registerConverter(new ActionEnumConvert())
                .registerConverter(new VendorEnumConvert())
                //.registerConverter(boardTypeEnumConvert2)
                .sheet().doRead();

        log.info("schemeExcelRecordList.size = {} ",schemeExcelRecordList.size());

    }

    public Map<String,BBUFrame>  buildBBUFrameList(List<SchemeExcelRecord> schemeExcelRecordList, List<CheckSchemeExcelRecord> checkSchemeExcelRecordList){
        Map<String,BBUFrame> bbuFrameMap=new HashMap<>();
        for (int i = 0; i < schemeExcelRecordList.size(); i++) {

            SchemeExcelRecord schemeExcelRecord=schemeExcelRecordList.get(i);
            String nodeBId=schemeExcelRecord.getNodeBId();
            BBUFrame bbuFrame=null;
            if(!bbuFrameMap.keySet().contains(nodeBId)){
                bbuFrame=new BBUFrame();

                // nodeB_Id 转换成数值
                try {
                    bbuFrame.setNodeBId(Integer.parseInt(schemeExcelRecord.getNodeBId().trim()));

                }catch (NumberFormatException numberFormatException){
                    CheckSchemeExcelRecord checkSchemeExcelRecord=new CheckSchemeExcelRecord();
                    checkSchemeExcelRecord.setMessage("nodeB_Id 输入错误。");
                    checkSchemeExcelRecord.setRowIndex(schemeExcelRecord.getRowIndex());
                    checkSchemeExcelRecordList.add(checkSchemeExcelRecord);
                    throw new RuntimeException(numberFormatException);
                }

                // 厂家，4/5G网络类型 转换成枚举，规范输入
                bbuFrame.setVendor(schemeExcelRecord.getVendor());
                bbuFrame.setGenerationType(schemeExcelRecord.getGenerationType());



                bbuFrame.setModel(schemeExcelRecord.getBbuModel());
                bbuFrameMap.put(nodeBId,bbuFrame);
            }else{
                bbuFrame=bbuFrameMap.get(nodeBId);
            }

            buildBbuSlot(bbuFrame,schemeExcelRecord);

        }



        return bbuFrameMap;
    }

    private void buildBbuSlot(BBUFrame bbuFrame, SchemeExcelRecord schemeExcelRecord) {
      Map<Integer, BBUSlot> bbuSlotMap=bbuFrame.getBbuSlotMap();
      BBUSlot bbuSlot=null;
      //无槽道，直接返回:todo:need fix
      if(schemeExcelRecord.getSlotIndex()==null || schemeExcelRecord.getSlotIndex().trim().equals("")){
          return;
      }

      Integer slotIndex=Integer.parseInt(schemeExcelRecord.getSlotIndex());

      if(bbuSlotMap.keySet().contains(slotIndex)){
          bbuSlot=bbuSlotMap.get(slotIndex);
      }else{
          bbuSlot=new BBUSlot();
      }
        bbuSlot.setSlotIndex(slotIndex);
        BbuBoard bbuBoard=new BbuBoard();
        bbuBoard.setBoardType(schemeExcelRecord.getBoardType());
        bbuBoard.setVendor(schemeExcelRecord.getVendor());
        bbuBoard.setGenerationType(schemeExcelRecord.getGenerationType());
        bbuBoard.setModel(schemeExcelRecord.getBoardModel());
        bbuSlot.getBbuBoardList().add(bbuBoard);
        bbuSlotMap.put(slotIndex,bbuSlot);
    }


}
